cmake_minimum_required(VERSION 3.10)

#----------------------- 默认配置参数 ----------------------

#工程名称（PROJECT_NAME 变量，默认取所在目录名称）
file(RELATIVE_PATH PROJECT_NAME ${CMAKE_CURRENT_LIST_DIR}/.. ${CMAKE_CURRENT_LIST_DIR})

#源码文件扩展名
set(SRC_EXTS *.cpp *.c *.cc)

#头文件扩展名
set(HEADER_EXTS *.h *.hpp)  
  
#需要排除的文件(列表)
list(APPEND EXCLUDES ".*/CMakeFiles/.*") 

#依赖的库
set(LIBS )

#编译器名称（COMPILE_NAME 变量，默认取当前目录名称）
file(RELATIVE_PATH COMPILE_NAME ${CMAKE_BINARY_DIR}/.. ${CMAKE_BINARY_DIR})


#----------------------- 加载外部配置文件(用于修改覆盖默认配置参数) ----------------------
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/config_local.cmake")	
	set(CONFIG_F "${CMAKE_CURRENT_LIST_DIR}/config_local.cmake")	
else()
	set(CONFIG_F "${CMAKE_CURRENT_LIST_DIR}/config.cmake")	
endif()
include("${CONFIG_F}" OPTIONAL)


#-------------------- 生成一个默认版本头文件 --------------------
file(MAKE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include")
if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/include/revision.h") 
file(WRITE "${CMAKE_CURRENT_LIST_DIR}/include/revision.h" //)
endif()

#----------------------- 查找所有源码文件和头文件 ----------------------
file(GLOB_RECURSE ALL_SRCS ${SRC_EXTS}) 
file(GLOB_RECURSE ALL_HEADERS ${HEADER_EXTS})


#----------------------- 按EXLUDES变量过滤掉不需要编译的文件 ----------------------
foreach(EXCL IN LISTS EXCLUDES) 
	list(FILTER ALL_SRCS EXCLUDE REGEX ${EXCL})
	list(FILTER ALL_HEADERS EXCLUDE REGEX ${EXCL})
endforeach()


#----------------------- 将每个头文件所在目录添加到include ----------------------
foreach(FILENAME IN LISTS ALL_HEADERS)
	get_filename_component(DIRNAME ${FILENAME} DIRECTORY)	
	if(NOT "${DIRNAME}" IN_LIST INCS)
		list(APPEND INCS ${DIRNAME})		
	endif()
endforeach()
foreach(INC IN LISTS INCS)
	include_directories(${INC})
endforeach()


#----------------------- 查找编译器 ------------------------
find_program(COMPILE_EXE ${COMPILE_NAME}-gcc)
if("${COMPILE_EXE}" STREQUAL "COMPILE_EXE-NOTFOUND")	
	#message("-- Compiler: default")
else()
    message("-- Compiler: ${COMPILE_NAME}")
	set(CMAKE_C_COMPILER ${COMPILE_NAME}-gcc)
	set(CMAKE_CXX_COMPILER ${COMPILE_NAME}-g++)
	find_program(CMAKE_AR ${COMPILE_NAME}-ar)
	if("${CMAKE_AR}" STREQUAL  "CMAKE_AR-NOTFOUND")
		set(CMAKE_AR "${COMPILE_NAME}-gcc-ar")
	endif()
	if("${COMPILE_NAME}" MATCHES ".*mingw.*")
		set(CMAKE_SYSTEM_NAME Windows)
	else()
		set(CMAKE_SYSTEM_NAME Linux)
	endif()
endif()

#----------------------- 根据源码文件类型确定语言 ----------------------
set(HAS_CXX 0)
foreach(FILENAME IN LISTS ALL_SRCS)
	get_filename_component(EXTNAME ${FILENAME} EXT)	
	if(NOT ${EXTNAME} STREQUAL ".c")	    
		set(HAS_CXX 1)	
	endif()
endforeach()
if(HAS_CXX)
project(${PROJECT_NAME} LANGUAGES C CXX)
else()
project(${PROJECT_NAME} LANGUAGES C)
endif()




#-------------------- Windows 默认设置 --------------------
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
	#file(GLOB_RECURSE RC_SRCS "*.rc")
	#add_compile_options(-DUNICODE -D_UNICODE)
	link_libraries(psapi ws2_32 mf mfreadwrite mfuuid mfplat)	
endif()


#----------------- 不依赖 libstdc++.so libgcc_s.so -------------------------
if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
	link_libraries(-s) #剥离调试符号
	if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
		link_libraries(-static)
	else()
		if(NOT EXISTS ${CMAKE_BINARY_DIR}/libstdc++.a)
			execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=libstdc++.a OUTPUT_VARIABLE LIBSTDCXXPATH OUTPUT_STRIP_TRAILING_WHITESPACE)
			if(${WIN32})
				execute_process(COMMAND copy /b /y ${LIBSTDCXXPATH} . WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
			else()
				execute_process(COMMAND ln -s ${LIBSTDCXXPATH} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
			endif()
		endif()
		link_libraries(-L. -static-libgcc)
	endif()
endif()	

#----------------------- 其他编译参数设置 ----------------------

#导出compile_commands.json文件
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)


#-------------------- 编译器默认选项 --------------------
if(${CMAKE_C_COMPILER_ID} STREQUAL MSVC) #vc
	add_compile_options(-D_CRT_SECURE_NO_WARNINGS)
else() #gcc
	add_compile_options(-Wall)	
endif()


#--------------------- 拷贝资源文件到输出目录 ----------------------
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/resource)
	file(GLOB_RECURSE RESS RELATIVE "${CMAKE_CURRENT_LIST_DIR}/resource" "${CMAKE_CURRENT_LIST_DIR}/resource/*" )
	foreach(F IN LISTS RESS)
	    get_filename_component(DIRNAME ${F} DIRECTORY)	
		file(COPY ${CMAKE_CURRENT_LIST_DIR}/resource/${F} DESTINATION ${CMAKE_BINARY_DIR}/${DIRNAME})
	endforeach()
endif()

#----------------------- 使用外部build.cmake ----------------------
if(DEFINED CONFIG_DIR)
include(${CONFIG_DIR}/build.cmake OPTIONAL)
if(EXISTS ${CONFIG_DIR}/build.cmake)	
	return()
endif()
endif()

#-------------------- 编译主程序 (debug版本默认以_test结尾，release版默认为工程名称) --------------------
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
	set(MAIN_TARGET_NAME ${PROJECT_NAME}_test)
else()
	set(MAIN_TARGET_NAME ${PROJECT_NAME})
endif()
add_executable(${MAIN_TARGET_NAME} ${ALL_SRCS} ${LIB_SRCS})

#-------------------- 链接主程序依赖的库 --------------------
foreach(DEP IN LISTS LIBS)
	target_link_libraries(${MAIN_TARGET_NAME} ${DEP} )
	add_dependencies(${MAIN_TARGET_NAME} ${DEP})		
endforeach()


#-------------------- 链接assets资源文件 --------------------
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/assets)
	file(COPY ${CMAKE_CURRENT_LIST_DIR}/assets DESTINATION .)
	set(ASSETS_OPT  -Wl,--format=binary)
	set(ASSETS_FILES  )	
	file(GLOB_RECURSE RESS RELATIVE "${CMAKE_CURRENT_LIST_DIR}/assets" "${CMAKE_CURRENT_LIST_DIR}/assets/*" )
	foreach(F IN LISTS RESS)
		#message(${F})		
	    set(ASSETS_OPT ${ASSETS_OPT} -Wl,assets/${F})
		set(ASSETS_FILES  ${ASSETS_FILES} ${CMAKE_CURRENT_LIST_DIR}/assets/${F})		
	endforeach()
	set(ASSETS_OPT ${ASSETS_OPT} -Wl,--format=default)	
	target_link_options(${MAIN_TARGET_NAME} PUBLIC ${ASSETS_OPT})
	set_target_properties(${MAIN_TARGET_NAME} PROPERTIES LINK_DEPENDS "${ASSETS_FILES}")
endif()

#-------------------- assets资源列表写入到头文件 --------------------
if(DEFINED RESS)
	set(ASSETS_SIM  "#pragma once\n")
	set(ASSETS_ITEM  "#define ASSETS_FILE_LIST {\\")
	foreach(F IN LISTS RESS)		
		string(REPLACE . _ SIM1 ${F})
		string(REPLACE / _ SIM ${SIM1})
		set(ASSETS_SIM  "${ASSETS_SIM}\nextern const unsigned char _binary_assets_${SIM}_start[];")
		set(ASSETS_SIM  "${ASSETS_SIM}\nextern const unsigned char _binary_assets_${SIM}_end[];")
		set(ASSETS_ITEM "${ASSETS_ITEM}\n    {\"${F}\", _binary_assets_${SIM}_start, _binary_assets_${SIM}_end},\\")
	endforeach()
	set(ASSETS_ITEM "${ASSETS_ITEM}\n}\n")
	set(ASSETS_SIM "${ASSETS_SIM}\n\n")	
	file(WRITE "${CMAKE_CURRENT_LIST_DIR}/include/assets.h" "${ASSETS_SIM}")
	file(APPEND "${CMAKE_CURRENT_LIST_DIR}/include/assets.h" "${ASSETS_ITEM}")
endif()

#-------------------- 引入外部包 --------------------
set(PROJECT_NAME ${MAIN_TARGET_NAME})
include(packages.cmake OPTIONAL)








